package pcloud.client.watcher;

import java.io.File;
import java.io.IOException;
import java.lang.Thread.State;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import pcloud.client.remoteservice.FTP4JService;
import pcloud.client.remoteservice.FileService;
import pcloud.client.remoteservice.ServerChangeService;
import pcloud.client.scheduler.TaskScheduler;
import pcloud.client.util.FileResourceInfo;
import pcloud.client.util.FileSystemDB;
import pcloud.client.util.GlobalConfig;
import pcloud.client.util.Logger;
import pcloud.client.util.TreeDB;
import pcloud.client.worker.CloudTask;
import pcloud.client.worker.DownloadTask;
import pcloud.client.worker.LocalCreateTask;
import pcloud.client.worker.LocalDeleteTask;
import pcloud.client.worker.LocalRenameTask;
import pcloud.client.worker.TaskMonitor;

public class FTPServerWatcher implements ServerWatcher,Runnable
{

    private TaskScheduler taskScheduler;
	private volatile boolean watcherOn;
	private Thread watcherThread;
	TreeDB<FileResourceInfo> localDB;


	public FTPServerWatcher(TaskScheduler taskScheduler, TreeDB<FileResourceInfo> localDB)
	{
        this.taskScheduler = taskScheduler;
		this.localDB = localDB;
	}


	public Thread getWorkingThread()
	{
		return watcherThread;
	}

	@Override
	public void start()
	{
		watcherThread = new Thread(this);
		watcherOn = true;
		State state = watcherThread.getState();
		logger.info("PollClientWatcher starting, current state: " + state);

		if (state.equals(State.TERMINATED) || state.equals(State.NEW)) {
			watcherThread.start();
		}
	}

	@Override
	public void stop()
	{
		watcherOn = false;
	}
	
	@Override
	public void run()
	{
		logger.info("FTPServerWatcher thread started!");
		while (watcherOn) {
			try {
				handleServerChange();
				Thread.sleep(300000);
			} catch (InterruptedException e) {
				logger.info("FTPServerWatcher exception!"+e.getMessage());
			}
		}
		logger.info("FTPServerWatcher thread ended!");
	}

	private void handleServerChange()
	{
		Properties serverTaskProperties = ServerChangeService.getChange();
		for (Map.Entry<Object, Object> taskEntry : serverTaskProperties.entrySet() )
		{
			String path = taskEntry.getKey().toString();
			String syncRootPath = GlobalConfig.getInstance().findRemoteSyncRoot(path);
			if (syncRootPath==null) {
				continue;
			}

			FileResourceInfo fileInfo = new FileResourceInfo();
			fileInfo.setFullPath(path);
			fileInfo.setRemote(true);
			
			String action = taskEntry.getValue().toString();
			if ("RMD".equals(action) || "MKD".equals(action)) {
				fileInfo.setFolder(true);
			}

			CloudTask task = "DELE".equals(action) ? new LocalDeleteTask(fileInfo) : 
				"RETR".equals(action) ? new DownloadTask(fileInfo)  : 
				"RNTO".equals(action) ? new LocalRenameTask(fileInfo)  :
				"MKD".equals(action) ? new LocalCreateTask(fileInfo)  :
				"RMD".equals(action) ? new LocalDeleteTask(fileInfo)  :
					null;
			if (task==null) {
				continue;
			}

			TaskMonitor monitor = "DELE".equals(action) ? new LocalDeleteMonitor(localDB) : 
				"RETR".equals(action) ? new DownloadMonitor(localDB)  : 
				"RNTO".equals(action) ? new LocalRenameMonitor(localDB)  :
				"MKD".equals(action) ? new LocalCreateMonitor(localDB)  :
				"RMD".equals(action) ? new LocalDeleteMonitor(localDB)  :
					null;
			if (monitor!=null) {
				task.setMonitor(monitor);
			}
			
			taskScheduler.add(task);
		}
	}
	
	public void testHandleServerChange()
	{
		handleServerChange();
	}

	@Override
	public void syncOnce()
	{
		//首先简单地下载所有服务器上的文件
		String serverRoot = GlobalConfig.getInstance().getProperty("serverRoot");
		String user = GlobalConfig.getInstance().getProperty("user");
		String password = GlobalConfig.getInstance().getProperty("password");
		
		FileService ftp = FTP4JService.createInstance(serverRoot, user,
				password);
		String[] paths = GlobalConfig.getInstance().getRemoteFolders();
		for (String path : paths) {
			traverseDownload(ftp, path);
		}
	}

	private void traverseDownload(FileService ftp, String path)
	{
		try {
			List<FileResourceInfo> filesInfo = ftp.list(path);
			for (FileResourceInfo fileInfo : filesInfo) {
				if (fileInfo.isFolder()) {
					FileResourceInfo localFileInfo = fileInfo.toLocal();
					if (localFileInfo==null) {
						continue;
					}
					String fullPath = localFileInfo.getFullPath();
					File file = new File(fullPath);
					file.mkdirs();
					traverseDownload(ftp, fileInfo.getFullPath());
				} else {
					ftp.downloadFile(fileInfo);
				}
			}
		} catch (IOException e) {
			logger.info("traverse download failed! \r\n"+e.getMessage());
		}
	}
	
	public static void main(String[] args)
	{
		FTPServerWatcher watcher = new FTPServerWatcher(new TaskScheduler(), new FileSystemDB<FileResourceInfo>());
		watcher.syncOnce();
	}
}
 